package edu.stanford.hardon;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

import edu.stanford.hardon.Media.Media;
import edu.stanford.hardon.Media.RichMedia;
import edu.stanford.hardon.Media.TextMedia;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;

public class UploadService extends Service {
	
	private Timer timer = new Timer();
	
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public void onCreate() {
		timer.scheduleAtFixedRate(new TimerTask() {
			public void run() {
				uploadAll();
			}
		}, 0, TravelHardConstants.UPLOAD_INTERVAL);
	}
	
	public void onDestroy() {
	}
	
	public int onStartCommand(Intent intent, int flags, int startid) {
	
		return 0;
	}
	
	private void uploadAll() {
		if (isNetworkAvailable()) {
			DatabaseHelper dbhh = TravelCore.getDBH();
			dbhh.open();
			List<Media> media = dbhh.getNonUploaded();
			dbhh.close();

			for (Media m : media) {
				upload(m);
			}
		}
	}
	
	private boolean isNetworkAvailable() {
	    ConnectivityManager connectivityManager = 
	    	(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
	    return activeNetworkInfo != null;
	}
	
	private void upload(final Media m) {	
			HttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(TravelHardConstants.UPLOAD_URL);
				
	    	try {
	    		httpPost.setEntity(buildEntity(m));
				httpClient.execute(httpPost, new ResponseHandler<Void>() {
					public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
						if (response.getStatusLine().getStatusCode() == 200) {
							m.setTimeUploaded(new Timestamp(new Date().getTime()));
							
							DatabaseHelper dbhh = TravelCore.getDBH();
							dbhh.open();
							dbhh.setUploaded(m);
							dbhh.close();
						}
						
						return null;
					}
				});
	    	} catch (UnsupportedEncodingException e) {
	    		// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    
	}
	
	private MultipartEntity buildEntity(Media m) throws UnsupportedEncodingException {
		MultipartEntity entity = new MultipartEntity();
		
		// Translate our Date value into a Timestamp that SQL can understand
		Timestamp timeCaptured = new Timestamp(m.getTimeCaptured().getTime());
		
		// Transmit this because parent_id references it
		entity.addPart("phone_db_id", new StringBody(m.getDBID().toString()));
		entity.addPart("trip_id", new StringBody(m.getTripID().toString()));
		entity.addPart("media_type", new StringBody(m.getType().toString()));
		entity.addPart("latitude", new StringBody(m.getLat().toString()));
		entity.addPart("longitude", new StringBody(m.getLng().toString()));
		entity.addPart("altitude", new StringBody(m.getAlt().toString()));
		entity.addPart("time_captured", new StringBody(timeCaptured.toString()));
		entity.addPart("parent_id", new StringBody(m.getParentId().toString()));

		if (m instanceof RichMedia) {
			entity.addPart("content", new FileBody(new File(((RichMedia)m).getPath())));
		} else if (m instanceof TextMedia) {
			entity.addPart("content", new StringBody(((TextMedia)m).getContent()));
		}
		
		return entity;
	}
	
}
